home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Tool Chest / Development Tools & Languages / Dylan Related / Mindy / Mindy 1.2 - portable sources / interp / func.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-15  |  55.3 KB  |  2,054 lines  |  [TEXT/ttxt]

  1. /**********************************************************************\
  2. *
  3. *  Copyright (c) 1994  Carnegie Mellon University
  4. *  All rights reserved.
  5. *  
  6. *  Use and copying of this software and preparation of derivative
  7. *  works based on this software are permitted, including commercial
  8. *  use, provided that the following conditions are observed:
  9. *  
  10. *  1. This copyright notice must be retained in full on any copies
  11. *     and on appropriate parts of any derivative works.
  12. *  2. Documentation (paper or online) accompanying any system that
  13. *     incorporates this software, or any part of it, must acknowledge
  14. *     the contribution of the Gwydion Project at Carnegie Mellon
  15. *     University.
  16. *  
  17. *  This software is made available "as is".  Neither the authors nor
  18. *  Carnegie Mellon University make any warranty about the software,
  19. *  its performance, or its conformity to any specification.
  20. *  
  21. *  Bug reports, questions, comments, and suggestions should be sent by
  22. *  E-mail to the Internet address "gwydion-bugs@cs.cmu.edu".
  23. *
  24. ***********************************************************************
  25. *
  26. * $Header: func.c,v 1.34 94/11/06 19:59:23 rgs Exp $
  27. *
  28. * This file implements functions.
  29. *
  30. \**********************************************************************/
  31.  
  32. #include "../compat/std-c.h"
  33.  
  34. #include "mindy.h"
  35. #include "gc.h"
  36. #include "thread.h"
  37. #include "bool.h"
  38. #include "list.h"
  39. #include "num.h"
  40. #include "class.h"
  41. #include "obj.h"
  42. #include "sym.h"
  43. #include "interp.h"
  44. #include "vec.h"
  45. #include "type.h"
  46. #include "module.h"
  47. #include "print.h"
  48. #include "driver.h"
  49. #include "error.h"
  50. #include "def.h"
  51. #include "extern.h"
  52. #include "func.h"
  53.  
  54. obj_t obj_FunctionClass = NULL;
  55. static obj_t obj_RawFunctionClass = NULL;
  56. obj_t obj_MethodClass = NULL;
  57. obj_t obj_ByteMethodClass = NULL;
  58. static obj_t obj_RawMethodClass;
  59. static obj_t obj_BuiltinMethodClass = NULL;
  60. static obj_t obj_AccessorMethodClass = NULL;
  61. obj_t obj_CFunctionClass = NULL;
  62. obj_t obj_GFClass = NULL;
  63. obj_t obj_MethodInfoClass = NULL;
  64. static obj_t obj_GFCacheClass = NULL;
  65.  
  66.  
  67. /* Tracing support. */
  68.  
  69. boolean Tracing = FALSE;
  70.  
  71. static void trace_call(obj_t function, obj_t *args, int nargs)
  72. {
  73.     printf("> 0x%08lx: ", (unsigned long)(args-1));
  74.     prin1(function_debug_name_or_self(function));
  75.     printf("(");
  76.     if (nargs > 0) {
  77.     prin1(*args++);
  78.     while (--nargs > 0) {
  79.         printf(", ");
  80.         prin1(*args++);
  81.     }
  82.     }
  83.     printf(")\n");
  84. }
  85.  
  86. static void trace_return(obj_t *old_sp, obj_t *vals, int nvals)
  87. {
  88.     printf("< 0x%08lx: ", (unsigned long)old_sp);
  89.     if (nvals > 0) {
  90.     prin1(*vals++);
  91.     while (--nvals > 0) {
  92.         printf(", ");
  93.         prin1(*vals++);
  94.     }
  95.     }
  96.     printf("\n");
  97. }
  98.  
  99.  
  100. /* Functions in general. */
  101.  
  102. struct gf_cache {
  103.     obj_t class;
  104.     boolean simple;
  105.     obj_t cached_result;
  106.     int size;
  107.     obj_t cached_classes[1];
  108. };
  109.  
  110. obj_t make_gf_cache(int req_args, obj_t cached_result)
  111. {
  112.     obj_t res = alloc(obj_GFCacheClass, 
  113.               (sizeof(struct gf_cache) 
  114.                + sizeof(obj_t)*(req_args - 1)));
  115.     struct gf_cache *gfc = obj_ptr(struct gf_cache *, res);
  116.     int i;
  117.  
  118.     gfc->simple = TRUE;
  119.     gfc->cached_result = cached_result;
  120.     gfc->size = req_args;
  121.     for (i = 0; i < req_args; i++)
  122.     gfc->cached_classes[i] = obj_Nil;
  123.  
  124.     return res;
  125. }
  126.  
  127. struct function {
  128.     obj_t class;
  129.     void (*xep)(struct thread *thread, int nargs);
  130.     obj_t debug_name;
  131.     int required_args;
  132.     boolean restp;
  133.     obj_t keywords;
  134.     boolean all_keys;
  135.     obj_t result_types;
  136.     obj_t more_results_type;
  137. };
  138.  
  139. #define FUNC(o) obj_ptr(struct function *, o)
  140.  
  141. obj_t make_raw_function(char *debug_name, int required_args,
  142.             boolean restp, obj_t keywords, boolean all_keys,
  143.             obj_t result_types, obj_t more_results_type,
  144.             void (*xep)(struct thread *thread, int nargs))
  145. {
  146.     obj_t res = alloc(obj_RawFunctionClass, sizeof(struct function));
  147.  
  148.     FUNC(res)->xep = xep;
  149.     FUNC(res)->debug_name = symbol(debug_name);
  150.     FUNC(res)->required_args = required_args;
  151.     FUNC(res)->restp = restp;
  152.     FUNC(res)->keywords = keywords;
  153.     FUNC(res)->all_keys = all_keys;
  154.     FUNC(res)->result_types = result_types;
  155.     FUNC(res)->more_results_type = more_results_type;
  156.  
  157.     return res;
  158. }
  159.  
  160. obj_t function_debug_name(obj_t function)
  161. {
  162.     return FUNC(function)->debug_name;
  163. }
  164.  
  165. obj_t function_debug_name_or_self(obj_t function)
  166. {
  167.     if (instancep(function, obj_FunctionClass)) {
  168.     obj_t debug_name = FUNC(function)->debug_name;
  169.  
  170.     if (debug_name == obj_False)
  171.         return function;
  172.     else
  173.         return debug_name;
  174.     }
  175.     else
  176.     return function;
  177. }
  178.  
  179. void invoke(struct thread *thread, int nargs)
  180. {
  181.     obj_t function = thread->sp[-nargs-1];
  182.     int required = FUNC(function)->required_args;
  183.     obj_t func_type = object_class(function);
  184.  
  185.     if (func_type != obj_BuiltinMethodClass
  186.     && func_type != obj_ByteMethodClass
  187.     && func_type != obj_BuiltinMethodClass
  188.     && func_type != obj_GFClass
  189.     && !subtypep(func_type, obj_FunctionClass))
  190.     lose("invoke called on a non-function.");
  191.  
  192.     if (Tracing)
  193.     trace_call(function, thread->sp - nargs, nargs);
  194.  
  195.     if (nargs < required) {
  196.     push_linkage(thread, thread->sp - nargs);
  197.     error("Too few arguments for %=: expected %d, got %d",
  198.           function_debug_name_or_self(function),
  199.           make_fixnum(required),
  200.           make_fixnum(nargs));
  201.     }
  202.     
  203.     if (!FUNC(function)->restp && FUNC(function)->keywords == obj_False
  204.       && nargs > required) {
  205.     push_linkage(thread, thread->sp - nargs);
  206.     error("Too many arguments for %=: expected %d, got %d",
  207.           function_debug_name_or_self(function),
  208.           make_fixnum(required),
  209.           make_fixnum(nargs));
  210.     }
  211.  
  212.     FUNC(function)->xep(thread, nargs);
  213. #if !SLOW_LONGJMP
  214.     go_on();
  215. #endif
  216. }
  217.  
  218. obj_t *push_linkage(struct thread *thread, obj_t *args)
  219. {
  220.     obj_t *fp = thread->sp += 4;
  221.  
  222.     fp[-4] = rawptr_obj(thread->fp);
  223.     fp[-3] = rawptr_obj(args-1);
  224.     fp[-2] = thread->component;
  225.     fp[-1] = make_fixnum(thread->pc);
  226.     thread->fp = fp;
  227.     thread->component = rawptr_obj(NULL);
  228.     thread->pc = 0;
  229.  
  230.     return fp;
  231. }
  232.  
  233. obj_t *pop_linkage(struct thread *thread)
  234. {
  235.     obj_t *fp = thread->fp;
  236.  
  237.     thread->fp = obj_rawptr(fp[-4]);
  238.     thread->component = fp[-2];
  239.     thread->pc = fixnum_value(fp[-1]);
  240.  
  241.     return obj_rawptr(fp[-3]);
  242. }
  243.  
  244. void set_c_continuation(struct thread *thread,
  245.             void (*cont)(struct thread *thread, obj_t *vals))
  246. {
  247.     thread->component = rawptr_obj(cont);
  248.     thread->pc = 0;
  249. }
  250.  
  251. #if SLOW_LONGJMP
  252. void do_return(struct thread *thread, obj_t *old_sp, obj_t *vals)
  253. #else
  254. void do_return_setup(struct thread *thread, obj_t *old_sp, obj_t *vals)
  255. #endif
  256. {
  257.     if (Tracing)
  258.     trace_return(old_sp, vals, thread->sp - vals);
  259.  
  260.     if (thread->pc)
  261.     do_byte_return(thread, old_sp, vals);
  262.     else {
  263.     void (*cont)(struct thread *thread, obj_t *vals)
  264.         = (void (*)(struct thread *thread, obj_t *vals))
  265.         obj_rawptr(thread->component);
  266.     if (cont) {
  267.         thread->component = rawptr_obj(NULL);
  268.         if (old_sp != vals) {
  269.         obj_t *src = vals, *dst = old_sp, *end = thread->sp;
  270.         while (src < end)
  271.             *dst++ = *src++;
  272.         thread->sp = dst;
  273.         }
  274.         (*cont)(thread, old_sp);
  275.     }
  276.     else
  277.         lose("Attempt to return, but no continuation established.\n");
  278.     }
  279. }
  280.  
  281. #if !SLOW_LONGJMP
  282. void do_return(struct thread *thread, obj_t *old_sp, obj_t *vals)
  283. {
  284.     do_return_setup(thread, old_sp, vals);
  285.     go_on();
  286. }
  287. #endif
  288.  
  289.  
  290. /* Methods */
  291.  
  292. struct method {
  293.     obj_t class;
  294.     void (*xep)(struct thread *thread, int nargs);
  295.     obj_t debug_name;
  296.     int required_args;
  297.     boolean restp;
  298.     obj_t keywords;
  299.     boolean all_keys;
  300.     obj_t result_types;
  301.     obj_t more_results_type;
  302.     obj_t specializers;
  303.     obj_t class_cache;            /* #F or a gf_cache */
  304.     void (*iep)(obj_t self, struct thread *thread, obj_t *args);
  305. };
  306.  
  307. #define METHOD(o) obj_ptr(struct method *, o)
  308.  
  309. static obj_t *push_keywords(obj_t *sp, obj_t keywords, obj_t *args, int nargs)
  310. {
  311.     while (keywords != obj_Nil) {
  312.     obj_t key_info = HEAD(keywords);
  313.     obj_t key = HEAD(key_info);
  314.     int i;
  315.  
  316.     for (i = 0; i < nargs; i += 2) {
  317.         if (key == args[i]) {
  318.         *sp++ = args[i+1];
  319.         goto next;
  320.         }
  321.     }
  322.     *sp++ = TAIL(key_info);
  323.  
  324.       next:
  325.     keywords = TAIL(keywords);
  326.     }
  327.     return sp;
  328. }
  329.  
  330. static void really_invoke_methods(obj_t method, obj_t next_methods,
  331.                   struct thread *thread, int nargs)
  332. {
  333.     obj_t *args = thread->sp - nargs;
  334.     boolean restp = METHOD(method)->restp;
  335.     obj_t keywords = METHOD(method)->keywords;
  336.     int req_args = METHOD(method)->required_args;
  337.     int rest_count = nargs - req_args;
  338.  
  339.     /* Change the function on the stack to be the next method so that */
  340.     /* backtraces look better. */
  341.     args[-1] = method;
  342.  
  343.     if (restp || keywords != obj_False) {
  344.     obj_t *ptr = thread->sp - rest_count;
  345.     obj_t rest = make_vector(rest_count, ptr);
  346.  
  347.     if (restp)
  348.         *ptr++ = rest;
  349.  
  350.     if (keywords != obj_False) {
  351.         if ((rest_count & 1) != 0) {
  352.         push_linkage(thread, args);
  353.         error("Odd number of keyword/value arguments.");
  354.         }
  355.  
  356.         ptr = push_keywords(ptr, keywords, SOVEC(rest)->contents,
  357.                 rest_count);
  358.     }
  359.  
  360.     thread->sp = ptr;
  361.     }
  362.  
  363.     /* add next-method info. */
  364.     *thread->sp++ = next_methods;
  365.  
  366.     METHOD(method)->iep(method, thread, args);
  367. }
  368.  
  369. void invoke_methods(obj_t method, obj_t next_methods,
  370.             struct thread *thread, int nargs)
  371. {
  372.     if (method == obj_False) {
  373.     push_linkage(thread, thread->sp - nargs);
  374.     error("It is ambiguous which of these methods to invoke:\n  %=",
  375.           next_methods);
  376.     }
  377.     else
  378.     really_invoke_methods(method, next_methods, thread, nargs);
  379. }
  380.  
  381. /* Version of applicable_method_p which does extra work to allow SAM caching 
  382.    for generic function dispatch.  The "cache" argument is carried across
  383.    several calls to gfd_applicable_method_p and may be modified to reflect a
  384.    more restrictive set of types. */
  385. static boolean
  386.     gfd_applicable_method_p(obj_t method, obj_t *args, obj_t cache)
  387. {
  388.     obj_t specializers = METHOD(method)->specializers;
  389.     obj_t *cached_classes = obj_ptr(struct gf_cache *, cache)->cached_classes;
  390.  
  391.     while (specializers != obj_Nil) {
  392.     obj_t arg = *args++;
  393.     obj_t arg_class = *cached_classes++;
  394.     obj_t specializer = HEAD(specializers);
  395.  
  396.     /* arg_class may be either a singleton, a limited_int, or a class.
  397.        This stuff has been worked out on a case by case basis.  It could
  398.        certainly be made clearer, but this could potentially reduce
  399.        the efficiency by a large margin. */
  400.     if (!subtypep(arg_class, specializer))
  401.         if (instancep(arg, specializer)) {
  402.         if (TYPE(specializer)->type_id == id_LimFixnum)
  403.             *(cached_classes - 1) =
  404.             (TYPE(arg_class)->type_id == id_LimFixnum
  405.              ? intersect_limited_fixnums(arg_class,specializer)
  406.              : specializer);
  407.         else if (TYPE(specializer)->type_id == id_LimBignum)
  408.             *(cached_classes - 1) =
  409.             (TYPE(arg_class)->type_id == id_LimBignum
  410.              ? intersect_limited_bignums(arg_class,specializer)
  411.              : specializer);
  412.         else
  413.             *(cached_classes - 1) = singleton(arg);
  414.         obj_ptr(struct gf_cache *, cache)->simple = FALSE;
  415.         } else {
  416.         if (overlapp(arg_class, specializer)) {
  417.             if (TYPE(specializer)->type_id == id_LimFixnum)
  418.             *(cached_classes - 1) =
  419.                 restrict_limited_fixnums(arg, arg_class,
  420.                              specializer);
  421.             else if (TYPE(specializer)->type_id == id_LimBignum)
  422.             *(cached_classes - 1) =
  423.                 restrict_limited_bignums(arg, arg_class,
  424.                              specializer);
  425.             else
  426.             *(cached_classes - 1) = restrict_type(specializer,
  427.                                   arg_class);
  428.             obj_ptr(struct gf_cache *, cache)->simple = FALSE;
  429.         }
  430.         return FALSE;
  431.         }
  432.     specializers = TAIL(specializers);
  433.     }
  434.     return TRUE;
  435. }
  436.  
  437. static boolean applicable_method_p(obj_t method, obj_t *args)
  438. {
  439.     obj_t cache = METHOD(method)->class_cache;
  440.     int max = METHOD(method)->required_args;
  441.     int i;
  442.     obj_t cache_elem, *cache_class, *arg;
  443.     boolean result;
  444.  
  445.     if (cache != obj_False) {
  446.     boolean found = TRUE;
  447.     struct gf_cache *c = obj_ptr(struct gf_cache *, cache);
  448.     register boolean simple = c->simple;
  449.  
  450.     cache_class = c->cached_classes;
  451.     arg = args;
  452.  
  453.     for (i = 0; i < max; i++, arg++, cache_class++) {
  454.         boolean simple_arg = simple ||
  455.         TYPE(*cache_class)->type_id == id_Class;
  456.         if (simple_arg ? *cache_class != object_class(*arg)
  457.                    : !instancep(*arg, *cache_class)) {
  458.         found = FALSE;
  459.         break;
  460.         }
  461.     }
  462.     if (found)
  463.         return TRUE;
  464.     }
  465.  
  466.     /* It wasn't in the cache.... */
  467.     cache_elem = (cache == obj_False) ? make_gf_cache(max, obj_False) : cache;
  468.     cache_class = obj_ptr(struct gf_cache *, cache_elem)->cached_classes;
  469.     arg = args;
  470.  
  471.     for (i = 0; i < max; i++, arg++, cache_class++)
  472.     *cache_class = object_class(*arg);
  473.  
  474.     result = gfd_applicable_method_p(method, args, cache_elem);
  475.     METHOD(method)->class_cache = cache_elem;
  476.     return result;
  477. }
  478.  
  479. static boolean method_accepts_keyword(obj_t method, obj_t keyword)
  480. {
  481.     obj_t keywords = METHOD(method)->keywords;
  482.  
  483.     assert(!METHOD(method)->all_keys);
  484.     assert(keywords != obj_False);
  485.  
  486.     while (keywords != obj_Nil) {
  487.     if (HEAD(HEAD(keywords)) == keyword)
  488.         return TRUE;
  489.     keywords = TAIL(keywords);
  490.     }
  491.     return FALSE;
  492. }
  493.  
  494. static void method_xep(struct thread *thread, int nargs)
  495. {
  496.     obj_t *args = thread->sp - nargs;
  497.     obj_t method = args[-1];
  498.  
  499.     if (applicable_method_p(method, args)) {
  500.     if (METHOD(method)->keywords != obj_False
  501.           && !METHOD(method)->all_keys) {
  502.         obj_t *ptr = args+METHOD(method)->required_args;
  503.         while (ptr < thread->sp) {
  504.         if (!method_accepts_keyword(method, *ptr)) {
  505.             push_linkage(thread, args);
  506.             error("Method %= does not accept the keyword %=",
  507.               function_debug_name_or_self(method), *ptr);
  508.         }
  509.         ptr += 2;
  510.         }
  511.     }
  512.     invoke_methods(method, obj_Nil, thread, nargs);
  513.     }
  514.     else {
  515.     push_linkage(thread, args);
  516.     error("Method %= is not applicable when given the arguments %=",
  517.           function_debug_name_or_self(method),
  518.           make_vector(nargs, args));
  519.     }
  520. }
  521.  
  522. obj_t make_raw_method(char *debug_name, obj_t specializers, boolean restp,
  523.               obj_t keywords, boolean all_keys, obj_t result_types,
  524.               obj_t more_results_type,
  525.               void (*iep)(obj_t self, struct thread *thread, obj_t *args))
  526. {
  527.     obj_t res = alloc(obj_RawMethodClass, sizeof(struct method));
  528.  
  529.     METHOD(res)->xep = method_xep;
  530.     METHOD(res)->debug_name = symbol(debug_name);
  531.     METHOD(res)->required_args = length(specializers);
  532.     METHOD(res)->restp = restp;
  533.     METHOD(res)->keywords = keywords;
  534.     METHOD(res)->all_keys = all_keys;
  535.     METHOD(res)->result_types = result_types;
  536.     METHOD(res)->more_results_type = more_results_type;
  537.     METHOD(res)->specializers = specializers;
  538.     METHOD(res)->class_cache = obj_False;
  539.     METHOD(res)->iep = iep;
  540.  
  541.     return res;
  542. }
  543.  
  544. void set_method_iep(obj_t method, 
  545.             void (*iep)(obj_t self, struct thread *thread, obj_t *args))
  546. {
  547.     METHOD(method)->iep = iep;
  548. }
  549.  
  550. static boolean same_specializers(obj_t specializers1, obj_t specializers2)
  551. {
  552.     obj_t scan1 = specializers1;
  553.     obj_t scan2 = specializers2;
  554.  
  555.     while (scan1 != obj_Nil) {
  556.     obj_t spec1 = HEAD(scan1);
  557.     obj_t spec2 = HEAD(scan2);
  558.  
  559.     if (!subtypep(spec1, spec2) || !subtypep(spec2, spec1))
  560.         return FALSE;
  561.  
  562.     scan1 = TAIL(scan1);
  563.     scan2 = TAIL(scan2);
  564.     }
  565.     return TRUE;
  566. }
  567.  
  568. enum method_comparison {
  569.     method_MoreSpecific, method_LessSpecific,
  570.     method_Identical, method_Ambiguous
  571. };
  572.  
  573. static enum method_comparison compare_methods(obj_t meth1, obj_t meth2,
  574.                           obj_t *args)
  575. {
  576.     boolean meth1_first = FALSE;
  577.     boolean meth2_first = FALSE;
  578.     obj_t scan1 = METHOD(meth1)->specializers;
  579.     obj_t scan2 = METHOD(meth2)->specializers;
  580.  
  581.     while (scan1 != obj_Nil) {
  582.     obj_t spec1 = HEAD(scan1);
  583.     obj_t spec2 = HEAD(scan2);
  584.     boolean spec1_more_specific = subtypep(spec1, spec2);
  585.     boolean spec2_more_specific = subtypep(spec2, spec1);
  586.  
  587.     if (spec1_more_specific && spec2_more_specific)
  588.         /* The two specializers are identical. */
  589.         ;
  590.     else if (spec1_more_specific) {
  591.         if (meth2_first)
  592.         return method_Ambiguous;
  593.         meth1_first = TRUE;
  594.     }
  595.     else if (spec2_more_specific) {
  596.         if (meth1_first)
  597.         return method_Ambiguous;
  598.         meth2_first = TRUE;
  599.     }
  600.     else if (instancep(spec1, obj_ClassClass)
  601.          && instancep(spec2, obj_ClassClass)) {
  602.         obj_t class = object_class(*args);
  603.         obj_t cpl = obj_ptr(struct class *, class)->cpl;
  604.  
  605.         while (cpl != obj_Nil) {
  606.         obj_t super = HEAD(cpl);
  607.         if (super == spec1) {
  608.             if (meth2_first)
  609.             return method_Ambiguous;
  610.             meth1_first = TRUE;
  611.             break;
  612.         }
  613.         if (super == spec2) {
  614.             if (meth1_first)
  615.             return method_Ambiguous;
  616.             meth2_first = TRUE;
  617.             break;
  618.         }
  619.         cpl = TAIL(cpl);
  620.         }
  621.         if (cpl == obj_Nil)
  622.         lose("Couldn't find either class in the objects cpl?");
  623.     }
  624.     else
  625.         return method_Ambiguous;
  626.  
  627.     scan1 = TAIL(scan1);
  628.     scan2 = TAIL(scan2);
  629.     args++;
  630.     }
  631.  
  632.     if (meth1_first)
  633.     return method_MoreSpecific;
  634.     else if (meth2_first)
  635.     return method_LessSpecific;
  636.     else
  637.     return method_Identical;
  638. }
  639.  
  640.  
  641. /* builtin methods. */
  642.  
  643. struct builtin_method {
  644.     obj_t class;
  645.     void (*xep)(struct thread *thread, int nargs);
  646.     obj_t debug_name;
  647.     int required_args;
  648.     boolean restp;
  649.     obj_t keywords;
  650.     boolean all_keys;
  651.     obj_t result_types;
  652.     obj_t more_results_type;
  653.     obj_t specializers;
  654.     obj_t class_cache;            /* #F or a gf_cache */
  655.     void (*iep)(obj_t self, struct thread *thread, obj_t *args);
  656.     obj_t (*func)();
  657. };
  658.  
  659. #define BUILTIN_METHOD(o) obj_ptr(struct builtin_method *, o)
  660.  
  661. static void builtin_method_iep_1_arg(obj_t method, struct thread *thread,
  662.                      obj_t *args)
  663. {
  664.     obj_t (*func)() = BUILTIN_METHOD(method)->func;
  665.     obj_t *old_sp;
  666.     obj_t value;
  667.  
  668.     push_linkage(thread, args);
  669.  
  670.     value = func(args[0]);
  671.  
  672.     old_sp = pop_linkage(thread);
  673.     *old_sp = value;
  674.     thread->sp = old_sp+1;
  675.  
  676.     do_return(thread, old_sp, old_sp);
  677. }
  678.  
  679. static void builtin_method_iep_2_args(obj_t method, struct thread *thread,
  680.                       obj_t *args)
  681. {
  682.     obj_t (*func)() = BUILTIN_METHOD(method)->func;
  683.     obj_t *old_sp;
  684.     obj_t value;
  685.  
  686.     push_linkage(thread, args);
  687.  
  688.     value = func(args[0], args[1]);
  689.  
  690.     old_sp = pop_linkage(thread);
  691.     *old_sp = value;
  692.     thread->sp = old_sp+1;
  693.  
  694.     do_return(thread, old_sp, old_sp);
  695. }
  696.  
  697. static void builtin_method_iep_3_args(obj_t method, struct thread *thread,
  698.                       obj_t *args)
  699. {
  700.     obj_t (*func)() = BUILTIN_METHOD(method)->func;
  701.     obj_t *old_sp;
  702.     obj_t value;
  703.  
  704.     push_linkage(thread, args);
  705.  
  706.     value = func(args[0], args[1], args[2]);
  707.  
  708.     old_sp = pop_linkage(thread);
  709.     *old_sp = value;
  710.     thread->sp = old_sp+1;
  711.  
  712.     do_return(thread, old_sp, old_sp);
  713. }
  714.  
  715. static void builtin_method_iep_4_args(obj_t method, struct thread *thread,
  716.                       obj_t *args)
  717. {
  718.     obj_t (*func)() = BUILTIN_METHOD(method)->func;
  719.     obj_t *old_sp;
  720.     obj_t value;
  721.  
  722.     push_linkage(thread, args);
  723.  
  724.     value = func(args[0], args[1], args[2], args[3]);
  725.  
  726.     old_sp = pop_linkage(thread);
  727.     *old_sp = value;
  728.     thread->sp = old_sp+1;
  729.  
  730.     do_return(thread, old_sp, old_sp);
  731. }
  732.  
  733. static void builtin_method_iep_5_args(obj_t method, struct thread *thread,
  734.                       obj_t *args)
  735. {
  736.     obj_t (*func)() = BUILTIN_METHOD(method)->func;
  737.     obj_t *old_sp;
  738.     obj_t value;
  739.  
  740.     push_linkage(thread, args);
  741.  
  742.     value = func(args[0], args[1], args[2], args[3], args[4]);
  743.  
  744.     old_sp = pop_linkage(thread);
  745.     *old_sp = value;
  746.     thread->sp = old_sp+1;
  747.  
  748.     do_return(thread, old_sp, old_sp);
  749. }
  750.  
  751. static void builtin_method_iep_6_args(obj_t method, struct thread *thread,
  752.                       obj_t *args)
  753. {
  754.     obj_t (*func)() = BUILTIN_METHOD(method)->func;
  755.     obj_t *old_sp;
  756.     obj_t value;
  757.  
  758.     push_linkage(thread, args);
  759.  
  760.     value = func(args[0], args[1], args[2], args[3], args[4], args[5]);
  761.  
  762.     old_sp = pop_linkage(thread);
  763.     *old_sp = value;
  764.     thread->sp = old_sp+1;
  765.  
  766.     do_return(thread, old_sp, old_sp);
  767. }
  768.  
  769. static void builtin_method_iep_7_args(obj_t method, struct thread *thread,
  770.                       obj_t *args)
  771. {
  772.     obj_t (*func)() = BUILTIN_METHOD(method)->func;
  773.     obj_t *old_sp;
  774.     obj_t value;
  775.  
  776.     push_linkage(thread, args);
  777.  
  778.     value = func(args[0], args[1], args[2], args[3],
  779.          args[4], args[5], args[6]);
  780.  
  781.     old_sp = pop_linkage(thread);
  782.     *old_sp = value;
  783.     thread->sp = old_sp+1;
  784.  
  785.     do_return(thread, old_sp, old_sp);
  786. }
  787.  
  788. static void builtin_method_iep_8_args(obj_t method, struct thread *thread,
  789.                       obj_t *args)
  790. {
  791.     obj_t (*func)() = BUILTIN_METHOD(method)->func;
  792.     obj_t *old_sp;
  793.     obj_t value;
  794.  
  795.     push_linkage(thread, args);
  796.  
  797.     value = func(args[0], args[1], args[2], args[3],
  798.          args[4], args[5], args[6], args[7]);
  799.  
  800.     old_sp = pop_linkage(thread);
  801.     *old_sp = value;
  802.     thread->sp = old_sp+1;
  803.  
  804.     do_return(thread, old_sp, old_sp);
  805. }
  806.  
  807. static void builtin_method_iep_9_args(obj_t method, struct thread *thread,
  808.                       obj_t *args)
  809. {
  810.     obj_t (*func)() = BUILTIN_METHOD(method)->func;
  811.     obj_t *old_sp;
  812.     obj_t value;
  813.  
  814.     push_linkage(thread, args);
  815.  
  816.     value = func(args[0], args[1], args[2], args[3], args[4],
  817.          args[5], args[6], args[7], args[8]);
  818.  
  819.     old_sp = pop_linkage(thread);
  820.     *old_sp = value;
  821.     thread->sp = old_sp+1;
  822.  
  823.     do_return(thread, old_sp, old_sp);
  824. }
  825.  
  826. static void builtin_method_iep_10_args(obj_t method, struct thread *thread,
  827.                        obj_t *args)
  828. {
  829.     obj_t (*func)() = BUILTIN_METHOD(method)->func;
  830.     obj_t *old_sp;
  831.     obj_t value;
  832.  
  833.     push_linkage(thread, args);
  834.  
  835.     value = func(args[0], args[1], args[2], args[3], args[4],
  836.          args[5], args[6], args[7], args[8], args[9]);
  837.  
  838.     old_sp = pop_linkage(thread);
  839.     *old_sp = value;
  840.     thread->sp = old_sp+1;
  841.  
  842.     do_return(thread, old_sp, old_sp);
  843. }
  844.  
  845. static void (*builtin_method_ieps[])(obj_t m, struct thread *t, obj_t *a) = {
  846.     NULL,
  847.     builtin_method_iep_1_arg,
  848.     builtin_method_iep_2_args,
  849.     builtin_method_iep_3_args,
  850.     builtin_method_iep_4_args,
  851.     builtin_method_iep_5_args,
  852.     builtin_method_iep_6_args,
  853.     builtin_method_iep_7_args,
  854.     builtin_method_iep_8_args,
  855.     builtin_method_iep_9_args,
  856.     builtin_method_iep_10_args
  857. };
  858.  
  859. #define MAX_BUILTIN_METHOD_ARGS (sizeof(builtin_method_ieps)/sizeof(builtin_method_ieps[0]))
  860.  
  861. obj_t make_builtin_method(char *debug_name, obj_t specializers,
  862.               boolean restp, obj_t keywords, boolean all_keys,
  863.               obj_t result_type, obj_t (*func)())
  864. {
  865.     obj_t res = alloc(obj_BuiltinMethodClass, sizeof(struct builtin_method));
  866.     int req_args = length(specializers);
  867.     int num_args = req_args + 1; /* Add one for the next methods */
  868.  
  869.     if (restp)
  870.     num_args++;
  871.     if (keywords != obj_False)
  872.     num_args += length(keywords);
  873.  
  874.     if (num_args >= MAX_BUILTIN_METHOD_ARGS)
  875.     lose("Can't make a builtin method that wants %d args -- %d at most.",
  876.          num_args, MAX_BUILTIN_METHOD_ARGS-1);
  877.  
  878.     BUILTIN_METHOD(res)->xep = method_xep;
  879.     BUILTIN_METHOD(res)->debug_name = symbol(debug_name);
  880.     BUILTIN_METHOD(res)->required_args = req_args;
  881.     BUILTIN_METHOD(res)->restp = restp;
  882.     BUILTIN_METHOD(res)->keywords = keywords;
  883.     BUILTIN_METHOD(res)->all_keys = all_keys;
  884.     BUILTIN_METHOD(res)->result_types = list1(result_type);
  885.     BUILTIN_METHOD(res)->more_results_type = obj_False;
  886.     BUILTIN_METHOD(res)->specializers = specializers;
  887.     BUILTIN_METHOD(res)->class_cache = obj_False;
  888.     BUILTIN_METHOD(res)->iep = builtin_method_ieps[num_args];
  889.     BUILTIN_METHOD(res)->func = func;
  890.  
  891.     return res;
  892. }
  893.  
  894.  
  895. /* byte methods */
  896.  
  897. struct byte_method {
  898.     obj_t class;
  899.     void (*xep)(struct thread *thread, int nargs);
  900.     obj_t debug_name;
  901.     int required_args;
  902.     boolean restp;
  903.     obj_t keywords;
  904.     boolean all_keys;
  905.     obj_t result_types;
  906.     obj_t more_results_type;
  907.     obj_t specializers;
  908.     obj_t class_cache;            /* #F or a gf_cache */
  909.     void (*iep)(obj_t self, struct thread *thread, obj_t *args);
  910.     obj_t component;
  911.     int n_closure_vars;
  912.     obj_t lexenv[1];
  913. };
  914.  
  915. #define BYTE_METHOD(o) obj_ptr(struct byte_method *, o)
  916.  
  917. obj_t byte_method_component(obj_t method)
  918. {
  919.     return BYTE_METHOD(method)->component;
  920. }
  921.  
  922. static void byte_method_iep(obj_t method, struct thread *thread, obj_t *args)
  923. {
  924.     int i, count;
  925.     obj_t *fp;
  926.  
  927.     /* push the closure vars */
  928.     count = BYTE_METHOD(method)->n_closure_vars;
  929.     for (i = 0; i < count; i++)
  930.     *thread->sp++ = BYTE_METHOD(method)->lexenv[i];
  931.  
  932.     fp = push_linkage(thread, args);
  933.     set_byte_continuation(thread, BYTE_METHOD(method)->component);
  934. #if !SLOW_LONGJMP
  935.     go_on();
  936. #endif
  937. }
  938.  
  939. obj_t make_method_info(boolean restp, obj_t keys, boolean all_keys,
  940.                obj_t component, int n_closure_vars)
  941. {
  942.     obj_t res = alloc(obj_MethodInfoClass, sizeof(struct method_info));
  943.  
  944.     METHOD_INFO(res)->restp = restp;
  945.     METHOD_INFO(res)->keys = keys;
  946.     METHOD_INFO(res)->all_keys = all_keys;
  947.     METHOD_INFO(res)->component = component;
  948.     METHOD_INFO(res)->n_closure_vars = n_closure_vars;
  949.  
  950.     return res;
  951. }
  952.  
  953. obj_t make_byte_method(obj_t method_info, obj_t specializers,
  954.                obj_t result_types, obj_t more_results_type,
  955.                obj_t *lexenv)
  956.                
  957. {
  958.     int n_closure_vars = METHOD_INFO(method_info)->n_closure_vars;
  959.     obj_t res = alloc(obj_ByteMethodClass,
  960.               sizeof(struct byte_method) + sizeof(obj_t)*(n_closure_vars - 1));
  961.     obj_t component = METHOD_INFO(method_info)->component;
  962.     int i;
  963.  
  964.     BYTE_METHOD(res)->xep = method_xep;
  965.     BYTE_METHOD(res)->debug_name = COMPONENT(component)->debug_name;
  966.     BYTE_METHOD(res)->required_args = length(specializers);
  967.     BYTE_METHOD(res)->restp = METHOD_INFO(method_info)->restp;
  968.     BYTE_METHOD(res)->keywords = METHOD_INFO(method_info)->keys;
  969.     BYTE_METHOD(res)->all_keys = METHOD_INFO(method_info)->all_keys;
  970.     BYTE_METHOD(res)->result_types = result_types;
  971.     if (more_results_type == obj_True)
  972.     BYTE_METHOD(res)->more_results_type = obj_ObjectClass;
  973.     else
  974.     BYTE_METHOD(res)->more_results_type = more_results_type;
  975.     BYTE_METHOD(res)->specializers = specializers;
  976.     BYTE_METHOD(res)->class_cache = obj_False;
  977.     BYTE_METHOD(res)->iep = byte_method_iep;
  978.     BYTE_METHOD(res)->component = component;
  979.     BYTE_METHOD(res)->n_closure_vars = n_closure_vars;
  980.     for (i = 0; i < n_closure_vars; i++)
  981.     BYTE_METHOD(res)->lexenv[i] = lexenv[i];
  982.  
  983.     return res;
  984. }
  985.  
  986.  
  987. /* Slot accessor methods. */
  988.  
  989. struct accessor_method {
  990.     obj_t class;
  991.     void (*xep)(struct thread *thread, int nargs);
  992.     obj_t debug_name;
  993.     int required_args;
  994.     boolean restp;
  995.     obj_t keywords;
  996.     boolean all_keys;
  997.     obj_t result_types;
  998.     obj_t more_results_type;
  999.     obj_t specializers;
  1000.     obj_t class_cache;            /* #F or a gf_cache */
  1001.     void (*iep)(obj_t self, struct thread *thread, obj_t *args);
  1002.     obj_t datum;
  1003. };
  1004.  
  1005. #define ACCESSOR_METHOD(o) obj_ptr(struct accessor_method *, o)
  1006.  
  1007. obj_t make_accessor_method(obj_t debug_name, obj_t class, obj_t type,
  1008.                boolean setter, obj_t datum,
  1009.                void (*iep)(obj_t self, struct thread *thread,
  1010.                     obj_t *args))
  1011. {
  1012.     obj_t res = alloc(obj_AccessorMethodClass, sizeof(struct accessor_method));
  1013.  
  1014.     ACCESSOR_METHOD(res)->xep = method_xep;
  1015.     ACCESSOR_METHOD(res)->debug_name = debug_name;
  1016.     ACCESSOR_METHOD(res)->required_args = setter ? 2 : 1;
  1017.     ACCESSOR_METHOD(res)->restp = FALSE;
  1018.     ACCESSOR_METHOD(res)->keywords = obj_False;
  1019.     ACCESSOR_METHOD(res)->all_keys = FALSE;
  1020.     ACCESSOR_METHOD(res)->result_types = list1(type);
  1021.     ACCESSOR_METHOD(res)->more_results_type = obj_False;
  1022.     ACCESSOR_METHOD(res)->specializers
  1023.     = setter ? list2(type, class) : list1(class);
  1024.     ACCESSOR_METHOD(res)->class_cache = obj_False;
  1025.     ACCESSOR_METHOD(res)->iep = iep;
  1026.     ACCESSOR_METHOD(res)->datum = datum;
  1027.  
  1028.     return res;
  1029. }
  1030.  
  1031. obj_t accessor_method_datum(obj_t method)
  1032. {
  1033.     return ACCESSOR_METHOD(method)->datum;
  1034. }
  1035.  
  1036. void set_accessor_method_datum(obj_t method, obj_t datum)
  1037. {
  1038.     ACCESSOR_METHOD(method)->datum = datum;
  1039. }
  1040.  
  1041.  
  1042. /* C functions. */
  1043.  
  1044. struct c_function {
  1045.     obj_t class;
  1046.     void (*xep)(struct thread *thread, int nargs);
  1047.     obj_t debug_name;
  1048.     int required_args;
  1049.     boolean restp;
  1050.     obj_t keywords;
  1051.     boolean all_keys;
  1052.     obj_t result_types;
  1053.     obj_t more_results_type;
  1054.     obj_t specializers;
  1055.     obj_t class_cache;            /* #F or a gf_cache */
  1056.     void (*iep)(obj_t self, struct thread *thread, obj_t *args);
  1057.     void *pointer;
  1058. };
  1059.  
  1060. #define C_FUNCTION(o) obj_ptr(struct c_function *, o)
  1061.  
  1062. static void c_function_xep(struct thread *thread, int nargs)
  1063. {
  1064.     obj_t *args = thread->sp - nargs;
  1065.     obj_t cf = args[-1];
  1066.     int (*fun)() = (int(*) ()) C_FUNCTION(cf)->pointer;
  1067.     obj_t res_type = HEAD(C_FUNCTION(cf)->result_types);
  1068.     int result;
  1069.     obj_t *old_sp;
  1070.     obj_t value;
  1071.  
  1072.     push_linkage(thread, args);
  1073.  
  1074.     switch (nargs) {
  1075.     case 0:
  1076.     result = fun();
  1077.     break;
  1078.     case 1:
  1079.     result = fun(get_c_object(args[0]));
  1080.     break;
  1081.     case 2:
  1082.     result = fun(get_c_object(args[0]), get_c_object(args[1]));
  1083.     break;
  1084.     case 3:
  1085.     result = fun(get_c_object(args[0]), get_c_object(args[1]),
  1086.              get_c_object(args[2]));
  1087.     break;
  1088.     case 4:
  1089.     result = fun(get_c_object(args[0]), get_c_object(args[1]),
  1090.              get_c_object(args[2]), get_c_object(args[3]),
  1091.              get_c_object(args[4]));
  1092.     break;
  1093.     case 5:
  1094.     result = fun(get_c_object(args[0]), get_c_object(args[1]),
  1095.              get_c_object(args[2]), get_c_object(args[3]),
  1096.              get_c_object(args[4]));
  1097.     break;
  1098.     case 6:
  1099.     result = fun(get_c_object(args[0]), get_c_object(args[1]),
  1100.              get_c_object(args[2]), get_c_object(args[3]),
  1101.              get_c_object(args[4]), get_c_object(args[5]));
  1102.     break;
  1103.     case 7:
  1104.     result = fun(get_c_object(args[0]), get_c_object(args[1]),
  1105.              get_c_object(args[2]), get_c_object(args[3]),
  1106.              get_c_object(args[4]), get_c_object(args[5]),
  1107.              get_c_object(args[6]));
  1108.     break;
  1109.     case 8:
  1110.     result = fun(get_c_object(args[0]), get_c_object(args[1]),
  1111.              get_c_object(args[2]), get_c_object(args[3]),
  1112.              get_c_object(args[4]), get_c_object(args[5]),
  1113.              get_c_object(args[6]), get_c_object(args[7]));
  1114.     break;
  1115.     case 9:
  1116.     result = fun(get_c_object(args[0]), get_c_object(args[1]),
  1117.              get_c_object(args[2]), get_c_object(args[3]),
  1118.              get_c_object(args[4]), get_c_object(args[5]),
  1119.              get_c_object(args[6]), get_c_object(args[7]),
  1120.              get_c_object(args[8]));
  1121.     break;
  1122.     case 10:
  1123.     result = fun(get_c_object(args[0]), get_c_object(args[1]),
  1124.              get_c_object(args[2]), get_c_object(args[3]),
  1125.              get_c_object(args[4]), get_c_object(args[5]),
  1126.              get_c_object(args[6]), get_c_object(args[7]),
  1127.              get_c_object(args[8]), get_c_object(args[9]));
  1128.     break;
  1129.     default:
  1130.     result = 0;        /* make compiler happy */
  1131.     lose("Can't call a c function with more than 10 args");
  1132.     }
  1133.  
  1134.     value = convert_c_object(res_type, (void *)result, TRUE);
  1135.  
  1136.     old_sp = pop_linkage(thread);
  1137.     *old_sp = value;
  1138.     thread->sp = old_sp+1;
  1139.  
  1140.     do_return(thread, old_sp, old_sp);
  1141. }
  1142.  
  1143. obj_t make_c_function(obj_t debug_name, void *pointer)
  1144. {
  1145.     obj_t res = alloc(obj_CFunctionClass, sizeof(struct c_function));
  1146.  
  1147.     C_FUNCTION(res)->xep = c_function_xep;
  1148.     C_FUNCTION(res)->debug_name = debug_name;
  1149.     C_FUNCTION(res)->required_args = 0;
  1150.     C_FUNCTION(res)->restp = TRUE;
  1151.     C_FUNCTION(res)->keywords = obj_False;
  1152.     C_FUNCTION(res)->all_keys = FALSE;
  1153.     C_FUNCTION(res)->result_types = obj_ObjectClass;
  1154.     C_FUNCTION(res)->more_results_type = obj_False;
  1155.     C_FUNCTION(res)->pointer = pointer;
  1156.     C_FUNCTION(res)->specializers = obj_Nil;
  1157.     C_FUNCTION(res)->class_cache = obj_False;
  1158.     C_FUNCTION(res)->iep = NULL;
  1159.  
  1160.     return res;
  1161. }
  1162.  
  1163. obj_t constrain_c_function(obj_t /* <c-function> */ res,
  1164.                obj_t /* <list> */ specializers,
  1165.                obj_t restp,
  1166.                obj_t /* <list> */ result_types)
  1167. {
  1168.     C_FUNCTION(res)->required_args = length(specializers);
  1169.     C_FUNCTION(res)->restp = (restp != obj_False);
  1170.     C_FUNCTION(res)->result_types = result_types;
  1171.     C_FUNCTION(res)->specializers = specializers;
  1172.  
  1173.     return res;
  1174. }
  1175.     
  1176.  
  1177. /* Generic functions. */
  1178.  
  1179. struct gf {
  1180.     obj_t class;
  1181.     void (*xep)(struct thread *thread, int nargs);
  1182.     obj_t debug_name;
  1183.     int required_args;
  1184.     boolean restp;
  1185.     obj_t keywords;
  1186.     boolean all_keys;
  1187.     obj_t result_types;
  1188.     obj_t more_results_type;
  1189.     obj_t methods;
  1190.     obj_t cache;
  1191. };
  1192.  
  1193. #define GF(o) obj_ptr(struct gf *, o)
  1194.  
  1195. static obj_t
  1196.     slow_sorted_applicable_methods(struct gf *gf, obj_t methods, obj_t *args)
  1197. {
  1198.     obj_t ordered = obj_Nil;
  1199.     obj_t ambiguous = obj_Nil;
  1200.     obj_t scan, *prev;
  1201.     int i, max = gf->required_args;
  1202.     obj_t cache_elem = make_gf_cache(max, obj_False);
  1203.     obj_t *cache = obj_ptr(struct gf_cache *, cache_elem)->cached_classes;
  1204.     obj_t *arg = args;
  1205.     
  1206.     for (i = 0; i < max; i++, arg++, cache++)
  1207.     *cache = object_class(*arg);
  1208.  
  1209.     while (methods != obj_Nil) {
  1210.     obj_t method = HEAD(methods);
  1211.  
  1212.     if (gfd_applicable_method_p(method, args, cache_elem)) {
  1213.         for (prev=&ordered; (scan=*prev) != obj_Nil; prev=&TAIL(scan)) {
  1214.         switch (compare_methods(method, HEAD(scan), args)) {
  1215.           case method_MoreSpecific:
  1216.             *prev = pair(method, scan);
  1217.             goto next;
  1218.           case method_LessSpecific:
  1219.             break;
  1220.           case method_Ambiguous:
  1221.             *prev = obj_Nil;
  1222.             ambiguous = list2(method, HEAD(scan));
  1223.             goto next;
  1224.           case method_Identical:
  1225.             lose("Two identical methods in the same "
  1226.              "generic function?");
  1227.         }
  1228.         }
  1229.         {
  1230.         obj_t new_ambiguous = obj_Nil;
  1231.         boolean more_specific = TRUE;
  1232.  
  1233.         for (scan = ambiguous; scan != obj_Nil; scan = TAIL(scan)) {
  1234.             switch (compare_methods(method, HEAD(scan), args)) {
  1235.               case method_MoreSpecific:
  1236.             break;
  1237.               case method_Ambiguous:
  1238.             new_ambiguous = pair(HEAD(scan), new_ambiguous);
  1239.             break;
  1240.               case method_LessSpecific:
  1241.             more_specific = FALSE;
  1242.             break;
  1243.               case method_Identical:
  1244.             lose("Two identical methods in the same "
  1245.                  "generic function?");
  1246.             }
  1247.         }
  1248.         if (new_ambiguous != obj_Nil)
  1249.             ambiguous = new_ambiguous;
  1250.         else if (more_specific)
  1251.             *prev = list1(method);
  1252.         }
  1253.     }
  1254.       next:
  1255.     methods = TAIL(methods);
  1256.     }
  1257.  
  1258.     if (ambiguous != obj_Nil) {
  1259.     for (prev = &ordered; (scan = *prev) != obj_Nil; prev = &TAIL(scan))
  1260.         ;
  1261.     *prev = pair(obj_False, ambiguous);
  1262.     }
  1263.  
  1264.     obj_ptr(struct gf_cache *, cache_elem)->cached_result = ordered;
  1265.     gf->cache = pair(cache_elem, gf->cache);
  1266.     return ordered;
  1267. }
  1268.  
  1269. static obj_t sorted_applicable_methods(obj_t gf, obj_t *args)
  1270. {
  1271.     struct gf *true_gf = GF(gf);
  1272.     obj_t *prev, cache;
  1273.     obj_t methods = true_gf->methods;
  1274.     int max = true_gf->required_args;
  1275.     
  1276.     /* If there are no methods, then nothing is applicable. */
  1277.     if (methods == obj_Nil)
  1278.     return obj_Nil;
  1279.  
  1280.     for (prev = &true_gf->cache, cache = *prev;
  1281.      cache != obj_Nil; prev = &TAIL(cache), cache = *prev) {
  1282.     struct gf_cache *cache_elem = obj_ptr(struct gf_cache *, HEAD(cache));
  1283.     register boolean simple = cache_elem->simple;
  1284.     obj_t *cache_class = cache_elem->cached_classes;
  1285.     obj_t *arg = args;
  1286.     int i;
  1287.     boolean found = TRUE;
  1288.  
  1289.     for (i = 0; i < max; i++, arg++, cache_class++) {
  1290.         boolean simple_arg = simple ||
  1291.         TYPE(*cache_class)->type_id == id_Class;
  1292.         if (simple_arg ? *cache_class != object_class(*arg)
  1293.                    : !instancep(*arg, *cache_class)) {
  1294.         found = FALSE;
  1295.         break;
  1296.         }
  1297.     }
  1298.  
  1299.     if (found) {
  1300.         *prev = TAIL(cache);
  1301.         TAIL(cache) = true_gf->cache;
  1302.         true_gf->cache = cache;
  1303.         return cache_elem->cached_result;
  1304.     }
  1305.     }
  1306.  
  1307.     /* We have to do it the slow way */
  1308.     return slow_sorted_applicable_methods(true_gf, methods, args);
  1309. }
  1310.  
  1311. static boolean methods_accept_keyword(obj_t methods, obj_t keyword)
  1312. {
  1313.     obj_t method;
  1314.  
  1315.     while (methods != obj_Nil && (method = HEAD(methods)) != obj_False) {
  1316.     if (method_accepts_keyword(method, keyword))
  1317.         return TRUE;
  1318.     methods = TAIL(methods);
  1319.     }
  1320.     return FALSE;
  1321. }
  1322.  
  1323. static void gf_xep(struct thread *thread, int nargs)
  1324. {
  1325.     obj_t *args = thread->sp - nargs;
  1326.     obj_t gf = args[-1];
  1327.     obj_t methods, primary_method;
  1328.  
  1329.     methods = sorted_applicable_methods(gf, args);
  1330.  
  1331.     if (methods != obj_Nil) {
  1332.     if (GF(gf)->keywords != obj_False && !GF(gf)->all_keys) {
  1333.         obj_t *ptr = args + GF(gf)->required_args;
  1334.         while (ptr < thread->sp) {
  1335.         if (!methods_accept_keyword(methods, *ptr)) {
  1336.             push_linkage(thread, args);
  1337.             error("The keyword %= is accepted by none of the "
  1338.               "applicable methods:\n  %=",
  1339.               *ptr, methods);
  1340.         }
  1341.         ptr += 2;
  1342.         }
  1343.     }
  1344.     primary_method = HEAD(methods);
  1345.     args[-1] = primary_method;
  1346.     invoke_methods(primary_method, TAIL(methods), thread, nargs);
  1347.     }
  1348.     else {
  1349.     push_linkage(thread, args);
  1350.     error("No applicable methods for %= with arguments %=",
  1351.           function_debug_name_or_self(gf),
  1352.           make_vector(nargs, args));
  1353.     }
  1354. }
  1355.  
  1356. obj_t make_generic_function(obj_t debug_name, int req_args, 
  1357.                 boolean restp, obj_t keywords, boolean all_keys,
  1358.                 obj_t result_types, obj_t more_results_type)
  1359. {
  1360.     obj_t res = alloc(obj_GFClass, sizeof(struct gf));
  1361.  
  1362.     GF(res)->xep = gf_xep;
  1363.     GF(res)->debug_name = debug_name;
  1364.     GF(res)->required_args = req_args;
  1365.     GF(res)->restp = restp;
  1366.     GF(res)->keywords = keywords;
  1367.     GF(res)->all_keys = all_keys;
  1368.     GF(res)->result_types = result_types;
  1369.     if (more_results_type == obj_True)
  1370.     GF(res)->more_results_type = obj_ObjectClass;
  1371.     else
  1372.     GF(res)->more_results_type = more_results_type;
  1373.     GF(res)->methods = obj_Nil;
  1374.     GF(res)->cache = obj_Nil;
  1375.  
  1376.     return res;
  1377. }
  1378.  
  1379. obj_t make_default_generic_function(obj_t debug_name, obj_t method)
  1380. {
  1381.     int reqargs = METHOD(method)->required_args;
  1382.     boolean restp = METHOD(method)->restp;
  1383.     obj_t keywords = METHOD(method)->keywords;
  1384.     boolean all_keys = METHOD(method)->all_keys;
  1385.  
  1386.     if (keywords != obj_False)
  1387.     keywords = obj_Nil;
  1388.  
  1389.     return make_generic_function(debug_name, reqargs, restp, keywords,
  1390.                  all_keys, obj_Nil, obj_ObjectClass);
  1391. }
  1392.  
  1393. void set_gf_signature(obj_t gf, int req_args, boolean restp, obj_t keys,
  1394.               boolean all_keys, obj_t result_types,
  1395.               obj_t more_results_type)
  1396. {
  1397.     obj_t methods = GF(gf)->methods;
  1398.  
  1399.     GF(gf)->required_args = req_args;
  1400.     GF(gf)->restp = restp;
  1401.     GF(gf)->keywords = keys;
  1402.     GF(gf)->all_keys = all_keys;
  1403.     GF(gf)->result_types = result_types;
  1404.     if (more_results_type == obj_True)
  1405.     GF(gf)->more_results_type = obj_ObjectClass;
  1406.     else
  1407.     GF(gf)->more_results_type = more_results_type;
  1408.     GF(gf)->methods = obj_Nil;
  1409.  
  1410.     while (methods != obj_Nil) {
  1411.     add_method(gf, HEAD(methods));
  1412.     methods = TAIL(methods);
  1413.     }
  1414. }
  1415.  
  1416. obj_t generic_function_methods(obj_t gf)
  1417. {
  1418.     return GF(gf)->methods;
  1419. }
  1420.  
  1421. obj_t generic_function_keywords(obj_t gf)
  1422. {
  1423.     return GF(gf)->keywords;
  1424. }
  1425.  
  1426. static obj_t really_add_method(obj_t gf, obj_t method)
  1427. {
  1428.     obj_t methods = GF(gf)->methods;
  1429.     obj_t specializers = METHOD(method)->specializers;
  1430.     obj_t scan;
  1431.  
  1432.     GF(gf)->cache = obj_Nil;
  1433.  
  1434.     for (scan = methods; scan != obj_Nil; scan = TAIL(scan)) {
  1435.     obj_t old = HEAD(scan);
  1436.     if (same_specializers(METHOD(old)->specializers, specializers)) {
  1437.         HEAD(scan) = method;
  1438.         return old;
  1439.     }
  1440.     }
  1441.     
  1442.     GF(gf)->methods = pair(method, methods);
  1443.     return obj_False;
  1444. }
  1445.  
  1446. obj_t add_method(obj_t gf, obj_t method)
  1447. {
  1448.     obj_t gfkeys;
  1449.     obj_t gfscan, methscan;
  1450.     int i;
  1451.  
  1452.     if (GF(gf)->required_args != METHOD(method)->required_args)
  1453.     error("%= has %d required arguments, but %= has %d",
  1454.           method, make_fixnum(METHOD(method)->required_args),
  1455.           gf, make_fixnum(GF(gf)->required_args));
  1456.  
  1457.     gfkeys = GF(gf)->keywords;
  1458.     if (gfkeys != obj_False) {
  1459.     /* The generic function takes keyword arguments. */
  1460.     obj_t methkeys = METHOD(method)->keywords;
  1461.  
  1462.     if (methkeys == obj_False)
  1463.         error("%= allows keyword arguments, but %= does not.", gf, method);
  1464.     while (gfkeys != obj_Nil) {
  1465.         obj_t gfkey = HEAD(gfkeys);
  1466.         obj_t scan;
  1467.  
  1468.         for (scan = methkeys; scan != obj_Nil; scan = TAIL(scan))
  1469.         if (HEAD(HEAD(scan)) == gfkey)
  1470.             goto okay;
  1471.         error("The keyword %= is mandatory for %=, "
  1472.           "but %= doesn't accept it.",
  1473.           gfkey, gf, method);
  1474.       okay:
  1475.         gfkeys = TAIL(gfkeys);
  1476.     }
  1477.  
  1478.     if (METHOD(method)->all_keys && !GF(gf)->all_keys)
  1479.         error("%= accepts all keys, but %= does not.", method, gf);
  1480.     }
  1481.     else if (METHOD(method)->keywords != obj_False)
  1482.     error("%= allows keyword arguments, but %= does not.", method, gf);
  1483.     else if (GF(gf)->restp) {
  1484.     if (!METHOD(method)->restp)
  1485.         error("%= accepts a variable number of arguments, "
  1486.           "but %= does not.",
  1487.           gf, method);
  1488.     }
  1489.     else if (METHOD(method)->restp)
  1490.     error("%= accepts a variable number of arguments, but %= does not.",
  1491.           method, gf);
  1492.  
  1493.     gfscan = GF(gf)->result_types;
  1494.     methscan = METHOD(method)->result_types;
  1495.     i = 0;
  1496.     while (gfscan != obj_Nil && methscan != obj_Nil) {
  1497.     obj_t gftype = HEAD(gfscan);
  1498.     obj_t methtype = HEAD(methscan);
  1499.  
  1500.     if (!subtypep(methtype, gftype))
  1501.         error("Result %= is an instance of %= for %=, "
  1502.           "but is an instance of %= for %=",
  1503.           make_fixnum(i), gftype, gf, methtype, method);
  1504.  
  1505.     gfscan = TAIL(gfscan);
  1506.     methscan = TAIL(methscan);
  1507.     i++;
  1508.     }
  1509.  
  1510.     if (gfscan != obj_Nil) {
  1511.     int gf_returns = i;
  1512.     while (gfscan != obj_Nil) {
  1513.         gf_returns++;
  1514.         gfscan = TAIL(gfscan);
  1515.     }
  1516.     if (GF(gf)->more_results_type != obj_False)
  1517.         error("%= returns at least %d results, but %= only returns %d",
  1518.           gf, make_fixnum(gf_returns), method, make_fixnum(i));
  1519.     else
  1520.         error("%= returns exactly %d results, but %= only returns %d",
  1521.           gf, make_fixnum(gf_returns), method, make_fixnum(i));
  1522.     }
  1523.     if (methscan != obj_Nil) {
  1524.     obj_t gftype = GF(gf)->more_results_type;
  1525.  
  1526.     if (gftype == obj_False) {
  1527.         int meth_returns = i;
  1528.         while (methscan != obj_Nil) {
  1529.         methscan = TAIL(methscan);
  1530.         meth_returns++;
  1531.         }
  1532.         if (METHOD(method)->more_results_type != obj_False)
  1533.         error("%= returns exactly %d results, "
  1534.               "but %= returns %d or more",
  1535.               gf, make_fixnum(i), method, make_fixnum(meth_returns));
  1536.         else
  1537.         error("%= returns exactly %d results, but %= returns %d",
  1538.               gf, make_fixnum(i), method, make_fixnum(meth_returns));
  1539.     }
  1540.     while (methscan != obj_Nil) {
  1541.         obj_t methtype = HEAD(methscan);
  1542.  
  1543.         if (!subtypep(methtype, gftype))
  1544.         error("Result %d is an instance of %= for %=, "
  1545.               "but is an instance of %= for %=",
  1546.               make_fixnum(i), gftype, gf, methtype, method);
  1547.  
  1548.         methscan = TAIL(methscan);
  1549.         i++;
  1550.     }
  1551.     }
  1552.  
  1553.     if (METHOD(method)->more_results_type != obj_False)
  1554.     if (GF(gf)->more_results_type != obj_False) {
  1555.         if (!subtypep(METHOD(method)->more_results_type,
  1556.               GF(gf)->more_results_type))
  1557.         error("Results %d and on are instances of %= for %=, "
  1558.               "but are instances of %= for %=",
  1559.               make_fixnum(i), GF(gf)->more_results_type, gf,
  1560.               METHOD(method)->more_results_type, method);
  1561.     }
  1562.     else
  1563.         error("%= returns exactly %d results, but %= returns %d or more",
  1564.           gf, make_fixnum(i), method, make_fixnum(i));
  1565.  
  1566.     return really_add_method(gf, method);
  1567. }
  1568.  
  1569.  
  1570. /* Dylan interface functions. */
  1571.  
  1572. static obj_t dylan_make_gf(obj_t debug_name, obj_t required,
  1573.                obj_t restp, obj_t keywords, obj_t all_keys,
  1574.                obj_t res_types, obj_t more_res_type)
  1575. {
  1576.     return make_generic_function(debug_name, fixnum_value(required),
  1577.                  restp != obj_False, keywords,
  1578.                  all_keys != obj_False, res_types,
  1579.                  more_res_type);
  1580. }
  1581.  
  1582. static void dylan_add_method(obj_t self, struct thread *thread, obj_t *args)
  1583. {
  1584.     obj_t *vals = args-1;
  1585.     obj_t gf = args[0];
  1586.     obj_t method = args[1];
  1587.     obj_t old = add_method(gf, method);
  1588.  
  1589.     thread->sp = vals + 2;
  1590.     vals[0] = method;
  1591.     vals[1] = old;
  1592.  
  1593.     do_return(thread, vals, vals);
  1594. }
  1595.  
  1596. static obj_t method_specializers(obj_t method)
  1597. {
  1598.     return METHOD(method)->specializers;
  1599. }
  1600.  
  1601. static void dylan_function_arguments(obj_t self, struct thread *thread,
  1602.                      obj_t *args)
  1603. {
  1604.     obj_t *vals = args-1;
  1605.     obj_t func = *args;
  1606.     obj_t keywords = FUNC(func)->keywords;
  1607.  
  1608.     thread->sp = vals + 3;
  1609.     vals[0] = make_fixnum(FUNC(func)->required_args);
  1610.     if (FUNC(func)->restp && keywords == obj_False)
  1611.     vals[1] = obj_True;
  1612.     else
  1613.     vals[1] = obj_False;
  1614.     vals[2] = FUNC(func)->all_keys ? symbol("all") : keywords;
  1615.  
  1616.     do_return(thread, vals, vals);
  1617. }
  1618.  
  1619. static void dylan_method_arguments(obj_t self, struct thread *thread,
  1620.                    obj_t *args)
  1621. {
  1622.     obj_t *vals = args-1;
  1623.     obj_t meth = *args;
  1624.     obj_t keywords = METHOD(meth)->keywords;
  1625.  
  1626.     thread->sp = vals + 3;
  1627.     vals[0] = make_fixnum(METHOD(meth)->required_args);
  1628.     if (METHOD(meth)->restp && keywords == obj_False)
  1629.     vals[1] = obj_True;
  1630.     else
  1631.     vals[1] = obj_False;
  1632.     if (METHOD(meth)->all_keys)
  1633.     vals[2] = symbol("all");
  1634.     else if (keywords != obj_False) {
  1635.     obj_t new = obj_Nil;
  1636.     while (keywords != obj_Nil) {
  1637.         new = pair(HEAD(HEAD(keywords)), new);
  1638.         keywords = TAIL(keywords);
  1639.     }
  1640.     vals[2] = new;
  1641.     }
  1642.     else
  1643.     vals[2] = obj_False;
  1644.  
  1645.     do_return(thread, vals, vals);
  1646. }
  1647.  
  1648. static obj_t dylan_sorted_app_meths(obj_t gf, obj_t args)
  1649. {
  1650.     int nargs = SOVEC(args)->length;
  1651.  
  1652.     if (nargs < GF(gf)->required_args)
  1653.     return obj_Nil;
  1654.     else
  1655.     return sorted_applicable_methods(gf, SOVEC(args)->contents);
  1656. }
  1657.  
  1658. static obj_t dylan_app_meth_p(obj_t method, obj_t args)
  1659. {
  1660.     int nargs = SOVEC(args)->length;
  1661.     
  1662.     if (nargs < METHOD(method)->required_args)
  1663.     return obj_False;
  1664.     else if (applicable_method_p(method, SOVEC(args)->contents))
  1665.     return obj_True;
  1666.     else
  1667.     return obj_False;
  1668. }
  1669.  
  1670. static obj_t dylan_find_method(obj_t gf, obj_t specializers)
  1671. {
  1672.     obj_t scan;
  1673.  
  1674.     for (scan = specializers; scan != obj_Nil; scan = TAIL(scan))
  1675.     check_type(HEAD(scan), obj_TypeClass);
  1676.  
  1677.     for (scan = GF(gf)->methods; scan != obj_Nil; scan = TAIL(scan)) {
  1678.     obj_t method = HEAD(scan);
  1679.     if (same_specializers(METHOD(method)->specializers, specializers))
  1680.         return method;
  1681.     }
  1682.  
  1683.     return obj_False;
  1684. }
  1685.  
  1686. static obj_t dylan_remove_method(obj_t gf, obj_t method)
  1687. {
  1688.     obj_t scan, *prev;
  1689.  
  1690.     GF(gf)->cache = obj_Nil;
  1691.  
  1692.     prev = &GF(gf)->methods;
  1693.     while ((scan = *prev) != obj_Nil) {
  1694.     if (method == HEAD(scan)) {
  1695.         *prev = TAIL(scan);
  1696.         return method;
  1697.     }
  1698.     prev = &TAIL(scan);
  1699.     }
  1700.     error("%= isn't one of the methods in %=", method, gf);
  1701.     return NULL;
  1702. }
  1703.  
  1704. static void dylan_do_next_method(obj_t self, struct thread *thread,
  1705.                  obj_t *args)
  1706. {
  1707.     obj_t methods = args[0];
  1708.     obj_t new_args = args[1];
  1709.     int len = SOVEC(new_args)->length;
  1710.     int i;
  1711.  
  1712.     for (i = 0; i < len; i++)
  1713.     args[i] = SOVEC(new_args)->contents[i];
  1714.     thread->sp = args + len;
  1715.  
  1716.     invoke_methods(HEAD(methods), TAIL(methods), thread, len);
  1717. }
  1718.  
  1719.  
  1720. /* Printer support. */
  1721.  
  1722. static void print_func(obj_t func)
  1723. {
  1724.     obj_t class = FUNC(func)->class;
  1725.     obj_t class_name = obj_ptr(struct class *, class)->debug_name;
  1726.     obj_t debug_name = FUNC(func)->debug_name;
  1727.     char *class_str;
  1728.  
  1729.     if (class_name != NULL && class_name != obj_False)
  1730.     class_str = sym_name(class_name);
  1731.     else
  1732.     class_str = "unknown function";
  1733.  
  1734.     if (debug_name != NULL && debug_name != obj_False) {
  1735.     printf("{%s ", class_str);
  1736.     prin1(debug_name);
  1737.     putchar('}');
  1738.     }
  1739.     else
  1740.     printf("{anonymous %s 0x%08lx}", class_str, (unsigned long)func);
  1741. }
  1742.  
  1743. static void print_method(obj_t method)
  1744. {
  1745.     obj_t class = METHOD(method)->class;
  1746.     obj_t class_name = obj_ptr(struct class *, class)->debug_name;
  1747.     obj_t debug_name = METHOD(method)->debug_name;
  1748.     char *class_str;
  1749.  
  1750.     if (class_name != NULL && class_name != obj_False)
  1751.     class_str = sym_name(class_name);
  1752.     else
  1753.     class_str = "unknown function";
  1754.  
  1755.     if (debug_name != NULL && debug_name != obj_False) {
  1756.     printf("{%s ", class_str);
  1757.     prin1(debug_name);
  1758.     putchar(' ');
  1759.     }
  1760.     else
  1761.     printf("{anonymous %s 0x%08lx ", class_str, (unsigned long)method);
  1762.  
  1763.  
  1764.     prin1(METHOD(method)->specializers);
  1765.     putchar('}');
  1766. }    
  1767.  
  1768.  
  1769. /* GC stuff. */
  1770.  
  1771. static void scav_func(struct function *func)
  1772. {
  1773.     scavenge(&func->debug_name);
  1774.     scavenge(&func->keywords);
  1775.     scavenge(&func->result_types);
  1776.     scavenge(&func->more_results_type);
  1777. }
  1778.  
  1779. static int scav_raw_func(struct object *ptr)
  1780. {
  1781.     scav_func((struct function *)ptr);
  1782.  
  1783.     return sizeof(struct function);
  1784. }
  1785.  
  1786. static obj_t trans_raw_func(obj_t func)
  1787. {
  1788.     return transport(func, sizeof(struct function));
  1789. }
  1790.  
  1791. static int scav_raw_method(struct object *ptr)
  1792. {
  1793.     scav_func((struct function *)ptr);
  1794.     scavenge(&((struct method *)ptr)->specializers);
  1795.     scavenge(&((struct method *)ptr)->class_cache);
  1796.  
  1797.     return sizeof(struct method);
  1798. }
  1799.     
  1800. static obj_t trans_raw_method(obj_t method)
  1801. {
  1802.     return transport(method, sizeof(struct method));
  1803. }
  1804.  
  1805. static int scav_builtin_method(struct object *ptr)
  1806. {
  1807.     scav_func((struct function *)ptr);
  1808.     scavenge(&((struct builtin_method *)ptr)->specializers);
  1809.     scavenge(&((struct builtin_method *)ptr)->class_cache);
  1810.  
  1811.     return sizeof(struct builtin_method);
  1812. }
  1813.     
  1814. static obj_t trans_builtin_method(obj_t method)
  1815. {
  1816.     return transport(method, sizeof(struct builtin_method));
  1817. }
  1818.  
  1819. static int scav_byte_method(struct object *ptr)
  1820. {
  1821.     struct byte_method *method = (struct byte_method *)ptr;
  1822.     int i;
  1823.  
  1824.     scav_func((struct function *)ptr);
  1825.     scavenge(&method->specializers);
  1826.     scavenge(&method->class_cache);
  1827.     scavenge(&method->component);
  1828.  
  1829.     for (i = 0; i < method->n_closure_vars; i++)
  1830.     scavenge(method->lexenv + i);
  1831.  
  1832.     return sizeof(struct byte_method) 
  1833.     + sizeof(obj_t)*(method->n_closure_vars - 1);
  1834. }
  1835.  
  1836. static obj_t trans_byte_method(obj_t method)
  1837. {
  1838.     int nvars = BYTE_METHOD(method)->n_closure_vars;
  1839.  
  1840.     return transport(method, sizeof(struct byte_method) 
  1841.              + sizeof(obj_t)*(nvars - 1));
  1842. }
  1843.  
  1844. static int scav_method_info(struct object *ptr)
  1845. {
  1846.     struct method_info *info = (struct method_info *)ptr;
  1847.  
  1848.     scavenge(&info->keys);
  1849.     scavenge(&info->component);
  1850.  
  1851.     return sizeof(struct method_info);
  1852. }
  1853.  
  1854. static obj_t trans_method_info(obj_t info)
  1855. {
  1856.     return transport(info, sizeof(struct method_info));
  1857. }
  1858.  
  1859. static int scav_accessor_method(struct object *ptr)
  1860. {
  1861.     struct accessor_method *method = (struct accessor_method *)ptr;
  1862.  
  1863.     scav_func((struct function *)ptr);
  1864.     scavenge(&method->specializers);
  1865.     scavenge(&method->class_cache);
  1866.     scavenge(&method->datum);
  1867.  
  1868.     return sizeof(struct accessor_method);
  1869. }
  1870.     
  1871. static obj_t trans_accessor_method(obj_t method)
  1872. {
  1873.     return transport(method, sizeof(struct accessor_method));
  1874. }
  1875.  
  1876. static int scav_c_function(struct object *ptr)
  1877. {
  1878.     scav_func((struct function *)ptr);
  1879.     scavenge(&((struct c_function *)ptr)->specializers);
  1880.  
  1881.     return sizeof(struct c_function);
  1882. }
  1883.     
  1884. static obj_t trans_c_function(obj_t method)
  1885. {
  1886.     return transport(method, sizeof(struct c_function));
  1887. }
  1888.  
  1889. static int scav_gf(struct object *ptr)
  1890. {
  1891.     struct gf *gf = (struct gf *)ptr;
  1892.  
  1893.     scav_func((struct function *)gf);
  1894.     scavenge(&gf->methods);
  1895.     scavenge(&gf->cache);
  1896.  
  1897.     return sizeof(struct gf);
  1898. }
  1899.  
  1900. static obj_t trans_gf(obj_t gf)
  1901. {
  1902.     return transport(gf, sizeof(struct gf));
  1903. }
  1904.  
  1905. static int scav_gf_cache(struct object *ptr)
  1906. {
  1907.     struct gf_cache *gf_cache = (struct gf_cache *)ptr;
  1908.     int i, max = gf_cache->size;
  1909.  
  1910.     scavenge(&gf_cache->cached_result);
  1911.     for (i = 0; i < max; i++)
  1912.     scavenge(&gf_cache->cached_classes[i]);
  1913.  
  1914.     return sizeof(struct gf_cache) + sizeof(obj_t)*(max - 1);
  1915. }
  1916.  
  1917. static obj_t trans_gf_cache(obj_t gf_cache)
  1918. {
  1919.     return transport(gf_cache, 
  1920.              (sizeof(struct gf_cache) 
  1921.               + sizeof(obj_t) 
  1922.                 * (obj_ptr(struct gf_cache *, gf_cache)->size - 1)));
  1923. }
  1924.  
  1925. void scavenge_func_roots(void)
  1926. {
  1927.     scavenge(&obj_FunctionClass);
  1928.     scavenge(&obj_RawFunctionClass);
  1929.     scavenge(&obj_MethodClass);
  1930.     scavenge(&obj_RawMethodClass);
  1931.     scavenge(&obj_BuiltinMethodClass);
  1932.     scavenge(&obj_ByteMethodClass);
  1933.     scavenge(&obj_AccessorMethodClass);
  1934.     scavenge(&obj_CFunctionClass);
  1935.     scavenge(&obj_MethodInfoClass);
  1936.     scavenge(&obj_GFClass);
  1937.     scavenge(&obj_GFCacheClass);
  1938. }
  1939.  
  1940.  
  1941. /* Init stuff. */
  1942.  
  1943. void make_func_classes(void)
  1944. {
  1945.     obj_FunctionClass = make_abstract_class(TRUE);
  1946.     obj_RawFunctionClass = make_builtin_class(scav_raw_func, trans_raw_func);
  1947.     obj_MethodClass = make_abstract_class(TRUE);
  1948.     obj_RawMethodClass
  1949.     = make_builtin_class(scav_raw_method, trans_raw_method);
  1950.     obj_BuiltinMethodClass
  1951.     = make_builtin_class(scav_builtin_method, trans_builtin_method);
  1952.     obj_ByteMethodClass
  1953.     = make_builtin_class(scav_byte_method, trans_byte_method);
  1954.     obj_AccessorMethodClass
  1955.     = make_builtin_class(scav_accessor_method, trans_accessor_method);
  1956.     obj_CFunctionClass
  1957.     = make_builtin_class(scav_c_function, trans_c_function);
  1958.     obj_MethodInfoClass
  1959.     = make_builtin_class(scav_method_info, trans_method_info);
  1960.     obj_GFClass = make_builtin_class(scav_gf, trans_gf);
  1961.     obj_GFCacheClass = make_builtin_class(scav_gf_cache, trans_gf_cache);
  1962. }
  1963.  
  1964. void init_func_classes(void)
  1965. {
  1966.     init_builtin_class(obj_FunctionClass, "<function>", obj_ObjectClass, NULL);
  1967.     def_printer(obj_FunctionClass, print_func);
  1968.     init_builtin_class(obj_RawFunctionClass, "<builtin-function>",
  1969.                obj_FunctionClass, NULL);
  1970.     init_builtin_class(obj_MethodClass, "<method>", obj_FunctionClass, NULL);
  1971.     def_printer(obj_MethodClass, print_method);
  1972.     init_builtin_class(obj_RawMethodClass, "<raw-method>",
  1973.                obj_MethodClass, NULL);
  1974.     init_builtin_class(obj_BuiltinMethodClass, "<builtin-method>",
  1975.                obj_MethodClass, NULL);
  1976.     init_builtin_class(obj_ByteMethodClass, "<byte-method>",
  1977.                obj_MethodClass, NULL);
  1978.     init_builtin_class(obj_MethodInfoClass, "<method-info>",
  1979.                obj_ObjectClass, NULL);
  1980.     init_builtin_class(obj_AccessorMethodClass, "<slot-accessor-method>",
  1981.                obj_MethodClass, NULL);
  1982.     init_builtin_class(obj_CFunctionClass, "<c-function>",
  1983.                obj_FunctionClass, NULL);
  1984.     init_builtin_class(obj_GFClass, "<generic-function>",
  1985.                obj_FunctionClass, NULL);
  1986.     init_builtin_class(obj_GFCacheClass, "<generic-function-cache>",
  1987.                obj_ObjectClass, NULL);
  1988. }
  1989.  
  1990. void init_func_functions(void)
  1991. {
  1992.     define_method("function-name", list1(obj_FunctionClass), FALSE, obj_False,
  1993.           FALSE, obj_ObjectClass, function_debug_name);
  1994.     define_function("make-generic-function",
  1995.             listn(7, obj_ObjectClass, obj_FixnumClass,
  1996.               obj_ObjectClass,
  1997.               type_union(object_class(obj_False), obj_ListClass),
  1998.               obj_ObjectClass, obj_ListClass,
  1999.               type_union(object_class(obj_False), obj_TypeClass)),
  2000.             FALSE, obj_False, FALSE,
  2001.             list1(obj_GFClass), dylan_make_gf);
  2002.     define_generic_function("add-method", 2, FALSE, obj_False, FALSE,
  2003.                 list2(obj_MethodClass,obj_ObjectClass), obj_False);
  2004.     add_method(find_variable(module_BuiltinStuff, symbol("add-method"),
  2005.                  FALSE, FALSE)->value,
  2006.            make_raw_method("add-method",list2(obj_GFClass,obj_MethodClass),
  2007.                    FALSE, obj_False, FALSE,
  2008.                    list2(obj_MethodClass, obj_ObjectClass),
  2009.                    obj_False, dylan_add_method));
  2010.     define_method("generic-function-methods", list1(obj_GFClass), FALSE,
  2011.           obj_False, FALSE, obj_ObjectClass, generic_function_methods);
  2012.     define_method("generic-function-mandatory-keywords", list1(obj_GFClass),
  2013.           FALSE, obj_False, FALSE, obj_ObjectClass,
  2014.           generic_function_keywords);
  2015.     define_method("method-specializers", list1(obj_MethodClass), FALSE,
  2016.           obj_False, FALSE, obj_ObjectClass, method_specializers);
  2017.     define_generic_function("function-arguments", 1, FALSE, obj_False, FALSE,
  2018.                 list3(obj_FixnumClass, obj_BooleanClass,
  2019.                   obj_ObjectClass),
  2020.                 obj_False);
  2021.     add_method(find_variable(module_BuiltinStuff, symbol("function-arguments"),
  2022.                  FALSE, FALSE)->value,
  2023.            make_raw_method("function-arguments", list1(obj_FunctionClass),
  2024.                    FALSE, obj_False, FALSE,
  2025.                    list3(obj_FixnumClass, obj_BooleanClass,
  2026.                      obj_ObjectClass),
  2027.                    obj_False, dylan_function_arguments));
  2028.     add_method(find_variable(module_BuiltinStuff, symbol("function-arguments"),
  2029.                  FALSE, FALSE)->value,
  2030.            make_raw_method("function-arguments", list1(obj_MethodClass),
  2031.                    FALSE, obj_False, FALSE,
  2032.                    list3(obj_FixnumClass, obj_BooleanClass,
  2033.                      obj_ObjectClass),
  2034.                    obj_False, dylan_method_arguments));
  2035.     define_method("sorted-applicable-methods", list1(obj_GFClass), TRUE,
  2036.           obj_False, FALSE, obj_ObjectClass, dylan_sorted_app_meths);
  2037.     define_method("applicable-method?", list1(obj_MethodClass), TRUE,
  2038.           obj_False, FALSE, obj_BooleanClass, dylan_app_meth_p);
  2039.     define_method("find-method", list2(obj_GFClass, obj_ListClass), FALSE,
  2040.           obj_False, FALSE, obj_ObjectClass, dylan_find_method);
  2041.     define_method("remove-method", list2(obj_GFClass, obj_MethodClass), FALSE,
  2042.           obj_False, FALSE, obj_ObjectClass, dylan_remove_method);
  2043.     define_constant("do-next-method",
  2044.             make_raw_method("do-next-method",
  2045.                     list2(obj_ObjectClass, obj_ObjectClass),
  2046.                     FALSE, obj_False, FALSE, obj_Nil,
  2047.                     obj_ObjectClass, dylan_do_next_method));
  2048.     define_method("constrain-c-function",
  2049.           listn(4, obj_CFunctionClass, obj_ListClass, 
  2050.             obj_ObjectClass, obj_ListClass),
  2051.           TRUE, obj_False, FALSE, obj_ObjectClass,
  2052.           constrain_c_function);
  2053. }
  2054.